﻿#include"XQSslServer.h"
#include<QSslSocket>
#include<QFile>
XQSslServer::XQSslServer(QObject* parent)
	:QTcpServer(parent)
{

}

QSslConfiguration* XQSslServer::sslConfiguration()
{
    return &m_sslConfiguration;
}

Http::Protocol XQSslServer::protocol() const
{
    return m_protocol;
}

void XQSslServer::setLocalCertificate(const QSslCertificate& certificate)
{
    m_sslConfiguration.setLocalCertificate(certificate);
}

void XQSslServer::setLocalCertificate(const QString& path, QSsl::EncodingFormat format)
{
    QFile file(path);
    file.open(QIODevice::ReadOnly | QIODevice::Text);
    setLocalCertificate(QSslCertificate(file.readAll(), format));
}

void XQSslServer::setPrivateKey(const QSslKey& key)
{
    m_sslConfiguration.setPrivateKey(key);
}

void XQSslServer::setPrivateKey(const QString& path, QSsl::KeyAlgorithm algorithm, QSsl::EncodingFormat encoding, QSsl::KeyType type, const QByteArray& passPhrase)
{
    QFile file(path);
    file.open(QIODevice::ReadOnly | QIODevice::Text);
    setPrivateKey(QSslKey(file.readAll(), algorithm, encoding, type, passPhrase));
}

void XQSslServer::setProtocol(Http::Protocol protocol)
{
    m_protocol = protocol;
}

bool XQSslServer::listen(const QHostAddress& address, quint16 port)
{
    if (protocol() == Http::Protocol::https&&(m_sslConfiguration.localCertificate().isNull() || m_sslConfiguration.privateKey().isNull()))
    {
        return false;
    }
    return QTcpServer::listen(address,port);
}

bool XQSslServer::isSslConnection(qintptr socketDescriptor)
{
    QTcpSocket* tempSocket=(new QTcpSocket());
    connect(tempSocket, &QTcpSocket::disconnected, tempSocket,&QObject::deleteLater);
    if (!tempSocket->setSocketDescriptor(socketDescriptor)) {
        qWarning() << "Failed to set socket descriptor(设置套接字描述符失败):" << tempSocket->errorString();
        return false;
    }
    tempSocket->waitForReadyRead();
    QByteArray peekData = tempSocket->peek(1);
    qDebug() << peekData;
    bool isSsl = (peekData.size() > 0 && peekData.at(0) == 0x16); // SSL 握手标识
    qDebug()<< tempSocket->socketDescriptor()<< socketDescriptor;
    return isSsl;
}

void XQSslServer::incomingConnection(qintptr socketDescriptor)
{
    //if(!isSslConnection(socketDescriptor))
    switch (protocol())
    {
    case Http::http:
    {
        QTcpServer::incomingConnection(socketDescriptor);
    }
        break;
    case Http::https:
    {
        QSslSocket* sslSocket = new QSslSocket(this);
        if (sslSocket->setSocketDescriptor(socketDescriptor))
        {
            sslSocket->ignoreSslErrors();
            sslSocket->setProtocol(QSsl::AnyProtocol);
            sslSocket->setSslConfiguration(m_sslConfiguration);
            //qDebug() << "开始握手";
            sslSocket->startServerEncryption();
            sslSocket->waitForEncrypted();
            if (sslSocket->isEncrypted())
            {
                //qDebug() << "握手成功";
                addPendingConnection(sslSocket);
                return;
            }
        }
        sslSocket->deleteLater();
    }
        break;
    default:
        break;
    }
}
